home *** CD-ROM | disk | FTP | other *** search
/ MacHack 2001 / MacHack 2001.toast / pc / The Hacks / Apple Turnover / HelloWorld.cp < prev    next >
Encoding:
Text File  |  2001-06-23  |  14.4 KB  |  733 lines

  1. #include <cmath>
  2. #include <cstdio> 
  3. #include <cstring>
  4. #include <memory>
  5.  
  6.  
  7. #include <LowMem.h>
  8. #include <QDOffscreen.h>
  9. #include <Quickdraw.h>
  10. #include <Retrace.h>
  11.  
  12.  
  13. #include <A4Stuff.h>
  14.  
  15.  
  16. // hash is not fully implemented
  17. #define HASH        0
  18.  
  19. // enable to get fps at the end
  20. #define PROFILE        0
  21.  
  22. // as well as being ugly, scale is broken
  23. #define SCALE    0
  24.  
  25.  
  26. #if VECTOR
  27. #include <altivec.h>
  28.  
  29. typedef union Float4
  30. {
  31.     float floats[4];
  32.     vector float vec;
  33. } Float4;
  34. #endif
  35.  
  36.  
  37. static pascal void Copier(VBLTaskPtr pTask);
  38. static void DrawRotatedImage(float rotation, bool drawCursor);
  39.  
  40. #if 0
  41. // not used, but cool
  42. static void PlotCursor(Cursor *pCurs);
  43. #endif
  44.  
  45. #if HASH
  46. void CheckHashes(short *pFirst, short *pLast);
  47. #endif
  48.  
  49. void ResetScreen();
  50.  
  51. void SetOn();
  52. void SetOff();
  53.  
  54.  
  55. void UpdateGlobals();
  56.  
  57.  
  58.  
  59. Ptr g_pBase;
  60. unsigned long g_ulHeight;
  61. unsigned long g_ulWidth;
  62. unsigned long g_ulCopySize;
  63. unsigned long g_ulRowBytes;
  64. Ptr g_pFakeBase;
  65. short g_nDepth;
  66.  
  67. bool g_bOn = false;
  68. bool g_bDone = false;
  69.  
  70. bool g_bUpdating = false;
  71.  
  72.  
  73. #if PROFILE
  74. unsigned long g_ulTicksElapsed = 0UL;
  75. unsigned long g_ulFrameCount = 0UL;
  76. #endif
  77.  
  78.  
  79. PixMapHandle g_hPM;
  80.  
  81.  
  82. #if HASH
  83. unsigned long *g_pHashes;
  84. #endif
  85.  
  86.  
  87. float g_dRotation = 0.0;
  88. extern const double_t pi;
  89.  
  90.  
  91. class Mgr
  92. {
  93.   public:
  94.     inline Mgr()
  95.     {
  96.         SetZone(SystemZone());
  97.  
  98.         m_sVBL.qLink = NULL;
  99.         m_sVBL.qType = vType;
  100.         m_sVBL.vblAddr = NewVBLUPP(Copier);
  101.         m_sVBL.vblCount = 1;
  102.         m_sVBL.vblPhase = 0;
  103.  
  104.         VInstall((QElemPtr)&m_sVBL);
  105.  
  106.         SetZone(ApplicationZone());
  107.     }
  108.  
  109.     inline ~Mgr()
  110.     {
  111.         SetZone(SystemZone());
  112.         VRemove((QElemPtr)&m_sVBL);
  113.         SetZone(ApplicationZone());
  114.         SetOff();
  115.     }
  116.  
  117.   private:
  118.     VBLTask m_sVBL;
  119. };
  120.  
  121.  
  122. int main()
  123. {
  124.     UpdateGlobals();
  125.  
  126.     char *pPtr = new char[g_ulCopySize];
  127.     g_pFakeBase = pPtr;
  128.  
  129. #if HASH
  130.     g_pHashes = new unsigned long[g_ulHeight];
  131.     std::memset(g_pHashes, 0, g_ulHeight * sizeof(unsigned long));
  132. #endif
  133.  
  134.     unsigned long ulTicks = TickCount();
  135.  
  136.     std::auto_ptr<Mgr> apMgr = std::auto_ptr<Mgr>(new Mgr);
  137.  
  138.     do
  139.     {
  140. //        std::printf(".");
  141.  
  142.         EventRecord event;
  143.         WaitNextEvent(0, &event, 60, NULL);
  144.  
  145. //        KeyMap keys;
  146. //        GetKeys(keys);
  147.  
  148. //        g_bDone = TickCount() - ulTicks > 60 * 30;//(((keys[1] >> 15) & 0x1) != 0 && ((keys[1] >> 23) & 0x1) != 0);
  149.     }
  150.     while(!g_bDone);
  151.  
  152.     delete(apMgr.release());
  153.  
  154.  
  155. #if PROFILE
  156.     Str255 strlDebug;
  157.     strlDebug[0] = std::snprintf((char *)&strlDebug[1], 255, "\n%lu frames in %lu ticks (%f fps)", g_ulFrameCount, g_ulTicksElapsed, (float)g_ulFrameCount * 60.0 / g_ulTicksElapsed);
  158.     DebugStr(strlDebug);
  159. #endif
  160.  
  161.  
  162.     return 0;
  163. }
  164.  
  165.  
  166. // constants
  167. #define kRadiansPerRevolution    (2.0 * pi)
  168.  
  169. #if SCALE
  170. #define kXScaleMin    ((float)g_ulHeight / (float)g_ulWidth)
  171. #define kXScaleMax    (1.0)
  172.  
  173. #define kYScaleMin    (1.0)
  174. #define kYScaleMax    ((float)g_ulWidth / (float)g_ulHeight)
  175. #endif
  176.  
  177. #define kGranularity    (bCapsLock ? 100.0 : 300.0)
  178.  
  179.  
  180. static pascal void Copier(VBLTaskPtr pTask)
  181. {
  182.     static unsigned long ulLast = 0UL;
  183.  
  184.     if(TickCount() - ulLast >= 3)
  185.     {
  186.         ulLast = TickCount();
  187.  
  188.         KeyMap keyMap;
  189.         GetKeys(keyMap);
  190.  
  191.         bool bEsc = (keyMap[1] & (0x1 << 13)) != 0;
  192.         bool bOpt = (keyMap[1] & (0x1 << 2)) != 0;
  193.         bool bCtrl = (keyMap[1] & (0x1 << 3)) != 0;
  194.         bool bCmd = (keyMap[1] & (0x1 << 15)) != 0;
  195.         bool bShift = (keyMap[1] & 0x1) != 0;
  196.         bool bCapsLock = (keyMap[1] & (0x1 << 1)) != 0;
  197.  
  198.         if(bCmd && bEsc)
  199.         {
  200.             g_bDone = true;
  201.         }
  202.  
  203.         if(bOpt) // opt
  204.         {
  205.             if(bCmd) // cmd
  206.             {
  207.                 g_dRotation -= kRadiansPerRevolution / kGranularity;
  208.             }
  209.             else
  210.             {
  211.                 g_dRotation += kRadiansPerRevolution / kGranularity;
  212.             }
  213.         }
  214.  
  215.         if(bCtrl && bEsc)
  216.         {
  217.             if(bShift)
  218.             {
  219.                 g_dRotation = pi;
  220.             }
  221.             else
  222.             {
  223.                 g_dRotation = 0.0;
  224.             }
  225.         }
  226.  
  227.         static bool sLastWasZero = true;
  228.  
  229.         if(g_bUpdating == false)
  230.         {
  231.         // special case for second and later 0s
  232.             if(g_dRotation == 0.0 && sLastWasZero)
  233.             {
  234.                 SetOff();
  235.             }
  236.             else
  237.             {
  238.                 SetOn();
  239.  
  240.                 sLastWasZero = false;
  241.                 if(g_dRotation == 0.0)
  242.                 {
  243.                     sLastWasZero = true;
  244.                 }
  245.  
  246.         #if PROFILE
  247.                 g_ulFrameCount++;
  248.                 g_ulTicksElapsed -= TickCount();
  249.         #endif
  250.                 DrawRotatedImage(g_dRotation, true);
  251.         #if PROFILE
  252.                 g_ulTicksElapsed += TickCount();
  253.         #endif
  254.             }
  255.         }
  256.     }
  257.     pTask->vblCount = 1;
  258. }
  259.  
  260.  
  261. #define InCursor(x, y)            (((y) >= cursTop && (y) < cursBottom) && ((x) >= cursLeft && (x) < cursRight))
  262. #define InCursorMaskRel(x, y)    (sCurs.mask[(y)] & (1 << (16 - (x) - 1)))
  263. #define InCursorMask(x, y)        InCursorMaskRel((x) - cursLeft, (y) - cursTop)
  264.  
  265. #define CursorDataIs1Rel(x, y)    (sCurs.data[(y)] & (1 << (16 - (x) - 1)))
  266. #define CursorDataIs1(x, y)        CursorDataIs1Rel((x) - cursLeft, (y) - cursTop)
  267.  
  268.  
  269. #if VECTOR
  270. #define XINCREMENT    4
  271. #else
  272. #define XINCREMENT    1
  273. #endif
  274.  
  275.  
  276. #define XSRC(n)    x_src ## n
  277. #define YSRC(n)    y_src ## n
  278. #define DST(n)    dst ## n
  279.  
  280. #define SetPixel(num)    \
  281. {    \
  282.     if(XSRC(num) > 0 && XSRC(num) < fullW && YSRC(num) > 0 && YSRC(num) < fullH)    \
  283.     {    \
  284.         if(!(drawCursor && InCursor(XSRC(num), YSRC(num)) && InCursorMask(XSRC(num), YSRC(num))))    \
  285.         {    \
  286.             *(short *)DST(num) = *(short *)(src + (XSRC(num) << 1L) + YSRC(num) * src_rowbytes);    \
  287.         }    \
  288.         else    \
  289.         {    \
  290.             *(short *)DST(num) = CursorDataIs1(XSRC(num), YSRC(num)) ? 0 : 0xffff;    \
  291.         }    \
  292.     }    \
  293.     else    \
  294.     {    \
  295.         *(short *)DST(num) = 0;    \
  296.     }    \
  297.     DST(num) += 8;    \
  298. }
  299.  
  300.  
  301. void DrawRotatedImage(float r, bool drawCursor)
  302. {
  303.     short    x, y, x_src, y_src;
  304.     Ptr        src, dst, next_dst;
  305.     short    src_rowbytes, dst_rowbytes;
  306.     float    r_sin, r_cos;
  307.     short    width, height;
  308.     float    rotation = (float)r;
  309.  
  310. #if SCALE
  311.     float    x_scale, y_scale;
  312. #endif
  313.  
  314.     src = g_pFakeBase;
  315.     src_rowbytes = g_ulRowBytes;
  316.  
  317.     next_dst = g_pBase;
  318.     dst_rowbytes = g_ulRowBytes;
  319.  
  320.     rotation = -rotation;
  321.  
  322.     r_sin = std::sin(rotation);
  323.     r_cos = std::cos(rotation);
  324.  
  325. #if SCALE
  326.     float scale = 0.5 - std::cos(-rotation * 2.0) / 2.0;
  327.  
  328.     x_scale = kXScaleMin + ((1.0 - scale) * (kXScaleMax - kXScaleMin));
  329.     y_scale = kYScaleMin + ((scale) * (kYScaleMax - kYScaleMin));
  330.  
  331.     x_scale = 1.0 / x_scale;
  332.     y_scale = 1.0 / y_scale;
  333. #endif
  334.  
  335.  
  336.     short first = 0, last = g_ulHeight;
  337.  
  338. #if HASH
  339.     CheckHashes(&first, &last);
  340. #endif
  341.  
  342.     width = (short)(g_ulWidth >> 1);
  343.     height = (short)(g_ulHeight >> 1);
  344.  
  345.     Cursor sCurs;
  346.  
  347.     LMGetTheCursor(&sCurs);
  348.     Point mouse = LMGetRawMouseLocation();
  349.  
  350.     short cursLeft = mouse.h - sCurs.hotSpot.h, cursRight = cursLeft + 16, cursTop = mouse.v - sCurs.hotSpot.v, cursBottom = cursTop + 16;
  351.  
  352.     first -= height;
  353.     last -= height;
  354.  
  355. #if VECTOR
  356.     Float4 float_trig;
  357.     float_trig.floats[0] = float_trig.floats[3] = r_cos;
  358.     float_trig.floats[1] = -r_sin;
  359.     float_trig.floats[2] = r_sin;
  360.  
  361.     vector float trig = vec_ld(0, float_trig.floats);
  362.  
  363.     Float4 float_halfs;
  364.     float_halfs.floats[0] = width;
  365.     float_halfs.floats[2] = height;
  366.     float_halfs.floats[1] = float_halfs.floats[3] = 0;
  367.  
  368.     vector float halfs = vec_ld(0, float_halfs.floats);
  369. #endif
  370.  
  371.     short fullW = g_ulWidth, fullH = g_ulHeight;
  372.  
  373.  
  374.     switch(g_nDepth)
  375.     {
  376.         case 8:
  377.             for(y = first; y < last; y++)
  378.             {
  379.                 dst = next_dst;
  380.                 next_dst += dst_rowbytes;
  381.  
  382.                 for(x = -width; x < width; x++)
  383.                 {
  384.                     x_src = (short)((float)x * r_cos - (float)y * r_sin);
  385.                     y_src = (short)((float)x * r_sin + (float)y * r_cos);
  386.  
  387. #if SCALE
  388.                     x_src *= x_scale;
  389.                     y_src *= y_scale;
  390. #endif
  391.  
  392.                     x_src += width;
  393.                     y_src += height;
  394.  
  395.                     if(x_src > 0 && x_src < 2 * width && y_src > 0 && y_src < 2 * height)
  396.                     {
  397.                         if(drawCursor && InCursor(x_src, y_src) && InCursorMask(x_src, y_src))
  398.                         {
  399.                             *(char *)dst = CursorDataIs1(x_src, y_src) ? 0xff : 0;
  400.                         }
  401.                         else
  402.                         {
  403.                             *(char *)dst = *(char *)(src + x_src + y_src * src_rowbytes);
  404.                         }
  405.                     }
  406.                     else
  407.                     {
  408.                         *(char *)dst = 0xff;
  409.                     }
  410.  
  411.                     dst += 1L;
  412.                 }
  413.             }
  414.             break;
  415.         case 16:
  416. #if VECTOR
  417.         // zero
  418.             Float4 float_zero;
  419.             float_zero.floats[0] = float_zero.floats[1] = float_zero.floats[2] = float_zero.floats[3] = 0;
  420.             vector float zero = vec_ld(0, float_zero.floats);
  421.  
  422.         // y vect
  423.             Float4 float_y_start;
  424.             float_y_start.floats[1] = float_y_start.floats[3] = first;
  425.             float_y_start.floats[0] = float_y_start.floats[2] = 0;
  426.             vector float vect_y_start = vec_ld(0, float_y_start.floats);
  427.             vector float vect_y = vect_y_start;
  428.  
  429.         // y increment
  430.             Float4 float_y_inc;
  431.             float_y_inc.floats[1] = float_y_inc.floats[3] = 1;
  432.             float_y_inc.floats[0] = float_y_inc.floats[2] = 0;
  433.             vector float vect_y_inc = vec_ld(0, float_y_inc.floats);
  434.  
  435.         // x increment
  436.             Float4 float_x_inc;
  437.             float_x_inc.floats[1] = float_x_inc.floats[3] = 0;
  438.             float_x_inc.floats[0] = float_x_inc.floats[2] = 1;
  439.             vector float vect_x_inc = vec_ld(0, float_x_inc.floats);
  440.         // x increment * 4
  441.             Float4 float_x_inc4;
  442.             float_x_inc4.floats[1] = float_x_inc4.floats[3] = 0;
  443.             float_x_inc4.floats[0] = float_x_inc4.floats[2] = 4;
  444.             vector float vect_x_inc4 = vec_ld(0, float_x_inc4.floats);
  445.  
  446.         // x vect
  447.             Float4 float_x_start;
  448.             float_x_start.floats[1] = float_x_start.floats[3] = 0;
  449.             float_x_start.floats[0] = float_x_start.floats[2] = -width;
  450.             vector float vect_x_start = vec_ld(0, float_x_start.floats);
  451. #endif
  452.  
  453.             for(y = first; y < last; y++)
  454.             {
  455.                 dst = next_dst;
  456.                 next_dst += dst_rowbytes;
  457.  
  458. #if VECTOR
  459.                 Float4 float_result0;
  460.                 Float4 float_result1;
  461.                 Float4 float_result2;
  462.                 Float4 float_result3;
  463.  
  464.                 vect_y = vec_add(vect_y_inc, vect_y);
  465.  
  466.                 vector float vect_x0 = vect_x_start;
  467.                 vector float vect_x1 = vec_add(vect_x_inc, vect_x0);
  468.                 vector float vect_x2 = vec_add(vect_x_inc, vect_x1);
  469.                 vector float vect_x3 = vec_add(vect_x_inc, vect_x2);
  470.  
  471.                 Ptr dst0 = dst;
  472.                 Ptr dst1 = dst + 2;
  473.                 Ptr dst2 = dst + 4;
  474.                 Ptr dst3 = dst + 6;
  475. #endif
  476.  
  477.                 for(x = -width; x < width; x += XINCREMENT)
  478.                 {
  479. #if VECTOR
  480.                 // increment x
  481.                     vect_x0 = vec_add(vect_x_inc4, vect_x0);
  482.                     vect_x1 = vec_add(vect_x_inc4, vect_x1);
  483.                     vect_x2 = vec_add(vect_x_inc4, vect_x2);
  484.                     vect_x3 = vec_add(vect_x_inc4, vect_x3);
  485.  
  486.                 // calculate op
  487.                     vector float op0 = vec_add(vect_x0, vect_y);
  488.                     vector float op1 = vec_add(vect_x1, vect_y);
  489.                     vector float op2 = vec_add(vect_x2, vect_y);
  490.                     vector float op3 = vec_add(vect_x3, vect_y);
  491.  
  492.                 // calculate!
  493.                     float_result0.vec = vec_madd(op0, trig, halfs);
  494.                     float_result1.vec = vec_madd(op1, trig, halfs);
  495.                     float_result2.vec = vec_madd(op2, trig, halfs);
  496.                     float_result3.vec = vec_madd(op3, trig, halfs);
  497.  
  498.                 // extract
  499.                     short x_src0 = (float_result0.floats[0] + float_result0.floats[1]);
  500.                     short y_src0 = (float_result0.floats[2] + float_result0.floats[3]);
  501.                     short x_src1 = (float_result1.floats[0] + float_result1.floats[1]);
  502.                     short y_src1 = (float_result1.floats[2] + float_result1.floats[3]);
  503.                     short x_src2 = (float_result2.floats[0] + float_result2.floats[1]);
  504.                     short y_src2 = (float_result2.floats[2] + float_result2.floats[3]);
  505.                     short x_src3 = (float_result3.floats[0] + float_result3.floats[1]);
  506.                     short y_src3 = (float_result3.floats[2] + float_result3.floats[3]);
  507.  
  508.                     SetPixel(0);
  509.                     SetPixel(1);
  510.                     SetPixel(2);
  511.                     SetPixel(3);
  512. #else
  513.                     x_src = (short)((float)x * r_cos - (float)y * r_sin);
  514.                     y_src = (short)((float)x * r_sin + (float)y * r_cos);
  515. #endif
  516.  
  517. #if SCALE
  518. #error
  519.                     x_src *= x_scale;
  520.                     y_src *= y_scale;
  521. #endif
  522.  
  523. #if !VECTOR
  524.                     x_src += width;
  525.                     y_src += height;
  526.  
  527.                     if(x_src > 0 && x_src < fullW && y_src > 0 && y_src < fullH)
  528.                     {
  529.                         if(drawCursor && InCursor(x_src, y_src) && InCursorMask(x_src, y_src))
  530.                         {
  531.                             *(short *)dst = CursorDataIs1(x_src, y_src) ? 0 : 0xffff;
  532.                         }
  533.                         else
  534.                         {
  535.                             *(short *)dst = *(short *)(src + (x_src << 1L) + y_src * src_rowbytes);
  536.                         }
  537.                     }
  538.                     else
  539.                     {
  540.                         *(short *)dst = 0;
  541.                     }
  542.  
  543.                     dst += 2L;
  544. #endif
  545.                 }
  546.             }
  547.             break;
  548.         case 32:
  549.             for(y = first; y < last; y++)
  550.             {
  551.                 dst = next_dst;
  552.                 next_dst += dst_rowbytes;
  553.  
  554.                 for(x = -width; x < width; x++)
  555.                 {
  556.                     x_src = (short)((float)x * r_cos - (float)y * r_sin);
  557.                     y_src = (short)((float)x * r_sin + (float)y * r_cos);
  558.  
  559. #if SCALE
  560.                     x_src *= x_scale;
  561.                     y_src *= y_scale;
  562. #endif
  563.  
  564.                     x_src += width;
  565.                     y_src += height;
  566.  
  567.                     if(x_src > 0 && x_src < 2 * width && y_src > 0 && y_src < 2 * height)
  568.                     {
  569.                         if(drawCursor && InCursor(x_src, y_src) && InCursorMask(x_src, y_src))
  570.                         {
  571.                             *(long *)dst = CursorDataIs1(x_src, y_src) ? 0 : 0xffffffff;
  572.                         }
  573.                         else
  574.                         {
  575.                             *(long *)dst = *(long *)(src + (x_src << 2L) + y_src * src_rowbytes);
  576.                         }
  577.                     }
  578.                     else
  579.                     {
  580.                         *(long *)dst = 0;
  581.                     }
  582.  
  583.                     dst += 4L;
  584.                 }
  585.             }
  586.             break;
  587.     }
  588. }
  589.  
  590.  
  591. #if 0
  592. // not used
  593.  
  594. static void PlotCursor(Cursor *pCurs)
  595. {
  596.     char * base = g_pFakeBase;
  597.     Point loc = LMGetRawMouseLocation();
  598.  
  599.     short vOffset = loc.v - pCurs->hotSpot.v;
  600.     short hOffset = loc.h - pCurs->hotSpot.h;
  601.  
  602.     for(int y = 0; y < 16; y++)
  603.     {
  604.         char * y_line = base + g_ulRowBytes * (vOffset + y);
  605.  
  606.         for(int x = 0; x < 16; x++)
  607.         {
  608.             if(pCurs->mask[y] & (1 << (16 - x - 1)))
  609.             {
  610.                 Ptr x_ptr = y_line + (hOffset + x) * (unsigned long)g_nDepth / 8;
  611.                 bool on = pCurs->data[y] & (1 << (16 - x - 1));
  612.  
  613.                 switch(g_nDepth)
  614.                 {
  615.                     case 16:
  616.                         *(short *)x_ptr = on ? 0 : 0xffff;
  617.                         break;
  618.                     case 32:
  619.                         *(unsigned long *)x_ptr = on ? 0 : 0xffffffff;
  620.                         break;
  621.                     case 8:
  622.                         *(unsigned char *)x_ptr = on ? 0xff : 0;
  623.                         break;
  624.                 }
  625.             }
  626.         }
  627.     }
  628. }
  629. #endif
  630.  
  631.  
  632.  
  633. void ResetScreen()
  634. {
  635.     g_dRotation = 0.0;
  636. //    DrawRotatedImage(g_dRotation, false);
  637.     std::memcpy(g_pBase, g_pFakeBase, g_ulCopySize);
  638. }
  639.  
  640.  
  641. void SetOn()
  642. {
  643.     if(g_bOn == false)
  644.     {
  645.         g_bOn = true;
  646.  
  647.         UpdateGlobals();
  648.  
  649.         std::memcpy(g_pFakeBase, g_pBase, g_ulCopySize);
  650.         HideCursor();
  651.         (**g_hPM).baseAddr = g_pFakeBase;
  652.     }
  653. }
  654.  
  655.  
  656. void SetOff()
  657. {
  658.     if(g_bOn)
  659.     {
  660.         g_bOn = false;
  661.  
  662.         (**g_hPM).baseAddr = g_pBase;
  663.         ResetScreen();
  664.         ShowCursor();
  665.     }
  666. }
  667.  
  668. #if HASH
  669.  
  670. void CheckHashes(short *pFirst, short *pLast)
  671. {
  672.     for(unsigned long y = 0; y < g_ulHeight; y++)
  673.     {
  674.         unsigned long ulHash = 0UL;
  675.  
  676.         for(unsigned long x = 0; x < g_ulWidth / sizeof(unsigned long); x++)
  677.         {
  678.             ulHash ^= ((unsigned long *)g_pFakeBase)[x];
  679.         }
  680.         if(ulHash != g_pHashes[y])
  681.         {
  682.             *pFirst = y;
  683.             g_pHashes[y] = ulHash;
  684.             goto findLast;
  685.         }
  686.     }
  687.  
  688. // no changes
  689.     *pFirst = *pLast = 0;
  690.     return;
  691.  
  692. findLast:
  693.     *pLast = *pFirst;
  694.  
  695.     for(unsigned long y = g_ulHeight - 1; y >= *pFirst; y--)
  696.     {
  697.         unsigned long ulHash = 0UL;
  698.  
  699.         for(unsigned long x = 0; x < g_ulWidth / sizeof(unsigned long); x++)
  700.         {
  701.             ulHash ^= ((unsigned long *)g_pFakeBase)[x];
  702.         }
  703.         if(ulHash != g_pHashes[y])
  704.         {
  705.             *pLast = y;
  706.             g_pHashes[y] = ulHash;
  707.             break;
  708.         }
  709.     }
  710. }
  711.  
  712. #endif
  713.  
  714. void UpdateGlobals()
  715. {
  716.     g_bUpdating = true;
  717.  
  718.     GDHandle hGD = LMGetTheGDevice();
  719.  
  720.     g_hPM = (**hGD).gdPMap;
  721.  
  722.     g_pBase = (**g_hPM).baseAddr;
  723.  
  724.     g_ulHeight = (**g_hPM).bounds.bottom - (**g_hPM).bounds.top;
  725.     g_ulWidth = (**g_hPM).bounds.right - (**g_hPM).bounds.left;
  726.     g_ulRowBytes = ((**g_hPM).rowBytes & 0x00007fff);
  727.     g_ulCopySize = g_ulHeight * g_ulRowBytes;
  728.  
  729.     g_nDepth = (**g_hPM).pixelSize;
  730.  
  731.     g_bUpdating = false;
  732. }
  733.